using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ThridGroup.ERP.Application.Contracts.OrderManagement;
using ThridGroup.ERP.DTO.OrderManagement;
using ThridGroup.ERP.OrderManagement;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using System.Text.Json;
using System.Text.Json.Serialization;
using Newtonsoft.Json;

namespace ThridGroup.ERP.Application.OrderManagement
{
    /// <summary>
    /// 销售订单服务实现
    /// </summary>
    public class SalesOrderService : ApplicationService, ISalesOrderService
    {
        private readonly IRepository<SalesOrderModel, int> _salesOrderRepository;
        private readonly ILogger<SalesOrderService> _logger;

        public SalesOrderService(
            IRepository<SalesOrderModel, int> salesOrderRepository,
            ILogger<SalesOrderService> logger)
        {
            _salesOrderRepository = salesOrderRepository;
            _logger = logger;
        }

        /// <summary>
        /// 添加销售订单
        /// </summary>
        [UnitOfWork]
        public async Task<int> AddSalesOrder(CreateUpdateSalesOrderDto input)
        {
            try
            {
                _logger.LogInformation($"开始添加销售订单：OrderCode={input.DOrderCode}, OrderName={input.DOrderName}");

                // 处理自动生成订单编码
                if (string.IsNullOrWhiteSpace(input.DOrderCode))
                {
                    input.DOrderCode = await GenerateOrderCodeAsync();
                    _logger.LogInformation($"自动生成订单编码：{input.DOrderCode}");
                }

                // 验证输入
                await ValidateSalesOrderInputAsync(input);
                
                // 备注字段已经在控制器层处理了产品明细数据，这里直接使用
                _logger.LogInformation($"接收到的备注字段内容：{input.DRemarks}");
                
                // 创建新实体
                var entity = new SalesOrderModel
                {
                    DOrderCode = input.DOrderCode?.Trim(),
                    DOrderName = input.DOrderName?.Trim(),
                    DCustomerCode = input.DCustomerCode?.Trim(),
                    DCustomerName = input.DCustomerName?.Trim(),
                    DCustomerPONumber = input.DCustomerPONumber?.Trim(),
                    DOrderDate = input.DOrderDate,
                    DeliveryDate = input.DeliveryDate?.Trim(),
                    DCurrency = input.DCurrency?.Trim(),
                    DSettlementMethod = input.DSettlementMethod?.Trim(),
                    DOrderCategory = input.DOrderCategory?.Trim(),
                    DOrderFollower = input.DOrderFollower?.Trim(),
                    DSalesperson = input.DSalesperson?.Trim(),
                    DQualityRequirement = input.DQualityRequirement?.Trim(),
                    DRemarks = input.DRemarks // 直接使用控制器层处理后的备注字段
                };

                _logger.LogInformation($"准备插入数据库，OrderCode：{entity.DOrderCode}，备注字段长度：{entity.DRemarks?.Length ?? 0}");
                
                // 插入数据库
                await _salesOrderRepository.InsertAsync(entity, true);
                
                _logger.LogInformation($"销售订单添加成功，ID：{entity.Id}");
                return entity.Id;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"添加销售订单失败：{ex.Message}");
                throw new Exception($"添加销售订单失败：{ex.Message}", ex);
            }
        }

        /// <summary>
        /// 生成订单编码
        /// </summary>
        private async Task<string> GenerateOrderCodeAsync()
        {
            try
            {
                // 获取当前日期
                var today = DateTime.Now;
                var datePrefix = today.ToString("yyyyMMdd");
                
                // 查询今天已有的订单数量
                var query = await _salesOrderRepository.GetQueryableAsync();
                var todayOrderCount = await query
                    .Where(x => x.DOrderCode.StartsWith("SO" + datePrefix))
                    .CountAsync();
                
                // 生成新的编码：SO + 日期 + 3位序号
                var orderCode = $"SO{datePrefix}{(todayOrderCount + 1):D3}";
                
                _logger.LogInformation($"生成订单编码：{orderCode}");
                return orderCode;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"生成订单编码失败：{ex.Message}");
                // 如果生成失败，使用时间戳作为备选方案
                return $"SO{DateTime.Now:yyyyMMddHHmmss}";
            }
        }

        /// <summary>
        /// 更新销售订单
        /// </summary>
        [UnitOfWork]
        public async Task<int> UpdateSalesOrder(int id, CreateUpdateSalesOrderDto input)
        {
            try
            {
                _logger.LogInformation($"开始更新销售订单，ID：{id}, OrderCode={input.DOrderCode}, OrderName={input.DOrderName}");

                // 验证ID
                if (id <= 0)
                {
                    throw new ArgumentException("无效的销售订单ID");
                }

                // 验证输入
                await ValidateSalesOrderInputAsync(input, id);

                try
                {
                    // 先获取现有实体
                    var entity = await _salesOrderRepository.GetAsync(id);
                    
                    if (entity == null)
                    {
                        throw new Exception($"未找到ID为{id}的销售订单");
                    }

                    // 备注字段已经在控制器层处理了产品明细数据，这里直接使用
                    _logger.LogInformation($"接收到的备注字段内容：{input.DRemarks}");

                    // 更新实体属性
                    entity.DOrderCode = input.DOrderCode?.Trim();
                    entity.DOrderName = input.DOrderName?.Trim();
                    entity.DCustomerCode = input.DCustomerCode?.Trim();
                    entity.DCustomerName = input.DCustomerName?.Trim();
                    entity.DCustomerPONumber = input.DCustomerPONumber?.Trim();
                    entity.DOrderDate = input.DOrderDate;
                    entity.DeliveryDate = input.DeliveryDate?.Trim();
                    entity.DCurrency = input.DCurrency?.Trim();
                    entity.DSettlementMethod = input.DSettlementMethod?.Trim();
                    entity.DOrderCategory = input.DOrderCategory?.Trim();
                    entity.DOrderFollower = input.DOrderFollower?.Trim();
                    entity.DSalesperson = input.DSalesperson?.Trim();
                    entity.DQualityRequirement = input.DQualityRequirement?.Trim();
                    entity.DRemarks = input.DRemarks; // 直接使用控制器层处理后的备注字段

                    _logger.LogInformation($"准备更新数据库，ID：{entity.Id}，备注字段长度：{entity.DRemarks?.Length ?? 0}");
                    
                    // 使用Repository的UpdateAsync方法
                    await _salesOrderRepository.UpdateAsync(entity, true);
                    
                    _logger.LogInformation($"销售订单更新成功，ID：{entity.Id}");
                    return entity.Id;
                }
                catch (Exception dbEx)
                {
                    _logger.LogError(dbEx, $"数据库更新错误：{dbEx.Message}");
                    throw new Exception($"数据库操作失败：{dbEx.Message}", dbEx);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"更新销售订单失败：{ex.Message}");
                throw new Exception($"更新销售订单失败：{ex.Message}", ex);
            }
        }

        /// <summary>
        /// 删除销售订单
        /// </summary>
        [UnitOfWork]
        public async Task DeleteSalesOrder(int id)
        {
            try
            {
                _logger.LogInformation($"开始删除销售订单，ID：{id}");

                // 验证ID
                if (id <= 0)
                {
                    throw new ArgumentException("无效的销售订单ID");
                }

                try
                {
                    // 先获取现有实体
                    var entity = await _salesOrderRepository.GetAsync(id);
                    
                    if (entity == null)
                    {
                        throw new Exception($"未找到ID为{id}的销售订单");
                    }

                    // 进行物理删除
                    _logger.LogInformation($"准备删除数据库记录，ID：{id}");
                    await _salesOrderRepository.DeleteAsync(entity, true);
                    
                    _logger.LogInformation($"销售订单删除成功，ID：{id}");
                }
                catch (Exception dbEx)
                {
                    _logger.LogError(dbEx, $"数据库删除错误：{dbEx.Message}");
                    throw new Exception($"数据库操作失败：{dbEx.Message}", dbEx);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"删除销售订单失败：{ex.Message}");
                throw new Exception($"删除销售订单失败：{ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取单个销售订单
        /// </summary>
        public async Task<SalesOrderDto> GetSalesOrder(int id)
        {
            try
            {
                _logger.LogInformation($"开始获取销售订单，ID：{id}");

                // 验证ID
                if (id <= 0)
                {
                    throw new ArgumentException("无效的销售订单ID");
                }

                try
                {
                    // 获取实体
                    var entity = await _salesOrderRepository.GetAsync(id);
                    
                    if (entity == null)
                    {
                        throw new Exception($"未找到ID为{id}的销售订单");
                    }

                    var dto = MapToDto(entity);
                    
                    _logger.LogInformation($"成功获取销售订单，ID：{id}");
                    return dto;
                }
                catch (Exception dbEx)
                {
                    _logger.LogError(dbEx, $"数据库查询错误：{dbEx.Message}");
                    throw new Exception($"数据库操作失败：{dbEx.Message}", dbEx);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取销售订单失败：{ex.Message}");
                throw new Exception($"获取销售订单失败：{ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取所有销售订单
        /// </summary>
        public async Task<List<SalesOrderDto>> GetSalesOrders()
        {
            try
            {
                _logger.LogInformation("开始获取所有销售订单");

                var entities = await _salesOrderRepository.GetListAsync();
                var dtos = entities.Select(MapToDto).ToList();
                
                _logger.LogInformation($"成功获取所有销售订单，总数：{dtos.Count}");
                return dtos;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取销售订单列表失败：{ex.Message}");
                throw new Exception($"获取销售订单列表失败：{ex.Message}", ex);
            }
        }

        /// <summary>
        /// 根据条件获取销售订单（支持所有字段）
        /// </summary>
        public async Task<List<SalesOrderDto>> GetSalesOrdersByCondition(
            string orderCode,
            string orderName,
            string customerCode,
            string customerName,
            string customerPONumber,
            string orderCategory,
            string orderType,
            string orderFollower,
            string salesperson,
            string qualityRequirement,
            string currency,
            string settlementMethod,
            string orderDateStart,
            string orderDateEnd,
            string deliveryDateStart,
            string deliveryDateEnd)
        {
            try
            {
                _logger.LogInformation($"开始按条件获取销售订单，orderCode={orderCode}, orderName={orderName}, customerCode={customerCode}, customerName={customerName}, customerPONumber={customerPONumber}, orderCategory={orderCategory}, orderType={orderType}, orderFollower={orderFollower}, salesperson={salesperson}, qualityRequirement={qualityRequirement}, currency={currency}, settlementMethod={settlementMethod}, orderDateStart={orderDateStart}, orderDateEnd={orderDateEnd}, deliveryDateStart={deliveryDateStart}, deliveryDateEnd={deliveryDateEnd}");

                var query = await _salesOrderRepository.GetQueryableAsync();
                if (!string.IsNullOrEmpty(orderCode))
                    query = query.Where(x => x.DOrderCode.Contains(orderCode));
                if (!string.IsNullOrEmpty(orderName))
                    query = query.Where(x => x.DOrderName.Contains(orderName));
                if (!string.IsNullOrEmpty(customerCode))
                    query = query.Where(x => x.DCustomerCode.Contains(customerCode));
                if (!string.IsNullOrEmpty(customerName))
                    query = query.Where(x => x.DCustomerName.Contains(customerName));
                if (!string.IsNullOrEmpty(customerPONumber))
                    query = query.Where(x => x.DCustomerPONumber.Contains(customerPONumber));
                if (!string.IsNullOrEmpty(orderCategory))
                    query = query.Where(x => x.DOrderCategory == orderCategory);
                if (!string.IsNullOrEmpty(orderType))
                    query = query.Where(x => x.DOrderCategory == orderType);
                if (!string.IsNullOrEmpty(orderFollower))
                    query = query.Where(x => x.DOrderFollower.Contains(orderFollower));
                if (!string.IsNullOrEmpty(salesperson))
                    query = query.Where(x => x.DSalesperson.Contains(salesperson));
                if (!string.IsNullOrEmpty(qualityRequirement))
                    query = query.Where(x => x.DQualityRequirement == qualityRequirement);
                if (!string.IsNullOrEmpty(currency))
                    query = query.Where(x => x.DCurrency == currency);
                if (!string.IsNullOrEmpty(settlementMethod))
                    query = query.Where(x => x.DSettlementMethod == settlementMethod);
                if (!string.IsNullOrEmpty(orderDateStart))
                {
                    if(DateTime.TryParse(orderDateStart, out var dtStart))
                        query = query.Where(x => x.DOrderDate >= dtStart);
                }
                if (!string.IsNullOrEmpty(orderDateEnd))
                {
                    if(DateTime.TryParse(orderDateEnd, out var dtEnd))
                        query = query.Where(x => x.DOrderDate <= dtEnd);
                }
                if (!string.IsNullOrEmpty(deliveryDateStart))
                {
                    if(DateTime.TryParse(deliveryDateStart, out var dtStart))
                        query = query.Where(x => x.DeliveryDate.CompareTo(deliveryDateStart) >= 0);
                }
                if (!string.IsNullOrEmpty(deliveryDateEnd))
                {
                    if(DateTime.TryParse(deliveryDateEnd, out var dtEnd))
                        query = query.Where(x => x.DeliveryDate.CompareTo(deliveryDateEnd) <= 0);
                }
                var entities = await query.ToListAsync();
                var dtos = entities.Select(MapToDto).ToList();
                _logger.LogInformation($"成功获取销售订单，总数：{dtos.Count}");
                return dtos;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"按条件获取销售订单列表失败：{ex.Message}");
                throw new Exception($"获取销售订单列表失败：{ex.Message}", ex);
            }
        }

        /// <summary>
        /// 检查订单编码是否存在
        /// </summary>
        public async Task<bool> IsOrderCodeExist(string orderCode, int? excludeId = null)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(orderCode))
                {
                    return false;
                }

                var query = await _salesOrderRepository.GetQueryableAsync();
                query = query.Where(x => x.DOrderCode == orderCode);
                
                if (excludeId.HasValue)
                {
                    query = query.Where(x => x.Id != excludeId.Value);
                }
                
                return await query.AnyAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"检查订单编码是否存在时出错：{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 验证销售订单输入
        /// </summary>
        private async Task ValidateSalesOrderInputAsync(CreateUpdateSalesOrderDto input, int? id = null)
        {
            // 必填字段验证
            if (string.IsNullOrWhiteSpace(input.DOrderCode))
            {
                throw new ArgumentException("订单编码不能为空");
            }

            if (string.IsNullOrWhiteSpace(input.DCustomerName))
            {
                throw new ArgumentException("客户名称不能为空");
            }

            // 验证编码唯一性（只有在订单编码不为空时才验证）
            if (!string.IsNullOrWhiteSpace(input.DOrderCode))
            {
                bool isOrderCodeExist = await IsOrderCodeExist(input.DOrderCode, id);
                if (isOrderCodeExist)
                {
                    throw new ArgumentException($"订单编码 '{input.DOrderCode}' 已存在");
                }
            }
        }

        /// <summary>
        /// 实体映射到DTO
        /// </summary>
        private SalesOrderDto MapToDto(SalesOrderModel entity)
        {
            if (entity == null)
            {
                return null;
            }

            // 从备注字段中分离用户备注和产品明细数据
            string userRemarks = ExtractUserRemarksFromCombined(entity.DRemarks);
            var productDetails = ExtractProductDetailsFromCombined(entity.DRemarks);

            return new SalesOrderDto
            {
                Id = entity.Id,
                DOrderCode = entity.DOrderCode,
                DOrderName = entity.DOrderName,
                DCustomerCode = entity.DCustomerCode,
                DCustomerName = entity.DCustomerName,
                DCustomerPONumber = entity.DCustomerPONumber,
                DOrderDate = entity.DOrderDate,
                DeliveryDate = entity.DeliveryDate,
                DCurrency = entity.DCurrency,
                DSettlementMethod = entity.DSettlementMethod,
                DOrderCategory = entity.DOrderCategory,
                DOrderFollower = entity.DOrderFollower,
                DSalesperson = entity.DSalesperson,
                DQualityRequirement = entity.DQualityRequirement,
                DRemarks = userRemarks,
                Products = productDetails ?? new List<SalesOrderProductDto>()
            };
        }

        /// <summary>
        /// 从组合的备注字段中提取用户备注部分
        /// </summary>
        /// <param name="combinedRemarks">组合的备注字段</param>
        /// <returns>用户备注部分</returns>
        private string ExtractUserRemarksFromCombined(string combinedRemarks)
        {
            if (string.IsNullOrEmpty(combinedRemarks))
            {
                return "";
            }

            // 查找产品明细数据的分隔符
            const string productPrefix = "||PRODUCTS:";
            int productIndex = combinedRemarks.IndexOf(productPrefix);
            
            if (productIndex >= 0)
            {
                // 返回分隔符之前的部分（用户备注）
                return combinedRemarks.Substring(0, productIndex).TrimEnd();
            }
            else
            {
                // 如果没有找到分隔符，说明没有产品明细数据，直接返回整个备注
                return combinedRemarks;
            }
        }

        /// <summary>
        /// 从组合的备注字段中提取产品明细数据
        /// </summary>
        /// <param name="combinedRemarks">组合的备注字段</param>
        /// <returns>产品明细列表</returns>
        private List<SalesOrderProductDto> ExtractProductDetailsFromCombined(string combinedRemarks)
        {
            var productDetails = new List<SalesOrderProductDto>();

            if (string.IsNullOrEmpty(combinedRemarks))
            {
                _logger.LogInformation("备注字段为空，返回空产品明细列表");
                return productDetails;
            }

            try
            {
                _logger.LogInformation($"开始解析备注字段内容：{combinedRemarks}");
                
                // 查找产品明细数据的分隔符
                const string productPrefix = "||PRODUCTS:";
                int productIndex = combinedRemarks.IndexOf(productPrefix);
                
                if (productIndex >= 0)
                {
                    string jsonData = combinedRemarks.Substring(productIndex + productPrefix.Length).Trim();
                    _logger.LogInformation($"提取到的JSON数据：{jsonData}");
                    
                    if (!string.IsNullOrEmpty(jsonData))
                    {
                        // 简化解析逻辑，直接使用Newtonsoft.Json
                        try
                        {
                            productDetails = Newtonsoft.Json.JsonConvert.DeserializeObject<List<SalesOrderProductDto>>(jsonData);
                            if (productDetails == null)
                            {
                                productDetails = new List<SalesOrderProductDto>();
                            }
                            _logger.LogInformation($"成功解析出 {productDetails.Count} 条产品明细");
                        }
                        catch (Exception jsonEx)
                        {
                            _logger.LogError(jsonEx, $"JSON解析失败：{jsonEx.Message}，JSON数据：{jsonData}");
                            productDetails = new List<SalesOrderProductDto>();
                        }
                    }
                    else
                    {
                        _logger.LogWarning("JSON数据为空");
                    }
                }
                else
                {
                    _logger.LogInformation($"备注字段中未找到产品明细标识符 '{productPrefix}'");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"提取产品明细数据失败：{ex.Message}");
                productDetails = new List<SalesOrderProductDto>();
            }

            return productDetails;
        }
    }
} 